home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 7
/
BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso
/
Files
/
Prog
/
Q-R
/
QB Graphics.sea
/
cube3d.bas
< prev
next >
Wrap
BASIC Source File
|
1991-06-04
|
10KB
|
367 lines
'------------------------------------------------------------------------------
' TITLE: cube3d
' DATE: April 19, 1991
' AUTHOR: R. Gonzalez
'
' DESCRIPTION: Demonstrates 3D perspective projection of cube. Uses mouse
' location to determine rotation amount. Uses a few tricks to accelerate
' performance, but note that after compilation the limiting factor is the
' Mac's graphics performance.
'
' COMPILING: Remove STATIC declarations, uncomment indicated lines
' Check: Include MBPCs & MBLCs, Include runtime code, Make all arrays static,
' Use default menu (if available: Generate 68020 & 68881 code).
'
' (MODIFICATION HISTORY)
' DATE:
' AUTHOR:
' DESCRIPTION:
'------------------------------------------------------------------------------
' Since mac windows use local coords (origin at top left), simplified formulas
' for 2D view transformation are used.
DEF FNxv%(xw) = (xw-xw1)*(xv2%-xv1%)/(xw2-xw1)
DEF FNyv%(yw) = (yw-yw1)*(yv2%-yv1%)/(yw2-yw1)
DIM SHARED xw1,xw2,yw1,yw2,xv1%,xv2%,yv1%,yv2%,d,p(4),pprime(4)
DIM SHARED TRUE%,FALSE%,pi,cube.dist
DIM SHARED num.points%,num.objects%,x(100),y(100),z(100),xp(100),yp(100)
DIM SHARED xtemp(100),ytemp(100),ztemp(100)
DIM SHARED pic1$,pic2$
'MAIN
DIM rot1(4,4),rot2(4,4),transl(4,4),composite(4,4),temp(4,4),yrot,xrot,junk%,mousex%,mousey%
DIM omousex%,omousey%
TRUE% = -1
FALSE% = 0
pi = 3.14159
cube.dist = 5
xrot = 0
yrot = 0
WINDOW CLOSE 1 'close default window
identity rot1()
identity rot2()
'identity transl()
set.view
initialize.world
omousex% = -1 'initialize with bad value
omousey% = -1
'animation loop (uses default QB File menu to quit)
WHILE TRUE%
junk% = MENU(0) 'must call menu(0) function to activate default menus
' This version doesn't need these operations because the cube remains at
' origin until just when it is ready to be drawn.
'translate 0!,0!,-cube.dist,transl()
junk% = MOUSE(0) 'must call mouse(0) to activate mouse functions
mousex% = MOUSE(1)
mousey% = MOUSE(2)
IF mousex% <> omousex% OR mousey% <> omousey% THEN 'don't redraw unless mouse moves
omousex% = mousex%
omousey% = mousey%
IF mousex% > 0 AND mousex% < (xv2%-xv1%) AND mousey% > 0 AND mousey% < (yv2%-yv1%) THEN
yrot = ((xv2%-xv1%)/2-mousex%)*pi/(xv2%-xv1%)
xrot = ((yv2%-yv1%)/2-mousey%)*pi/(yv2%-yv1%)
END IF
rotate.y yrot,rot1()
rotate.x xrot,rot2()
mat.mat rot1(),rot2(),composite()
'mat.mat transl(),rot(),composite()
'mat.copy temp(),composite()
'translate 0!,0!,cube.dist,transl()
'mat.mat temp(),transl(),composite()
transform.temp.world composite()
'CLS
draw.temp.world
END IF
WEND
END
'------------------------------------------------------------------------------
' transform all points in 3D world
'------------------------------------------------------------------------------
SUB transform.temp.world (trans()) STATIC
'for compiler only:
' dim i%
FOR i% = 1 TO num.points%
p(1) = x(i%)
p(2) = y(i%)
p(3) = z(i%)
p(4) = 1
vect.mat p(),trans(),pprime()
xtemp(i%) = pprime(1)
ytemp(i%) = pprime(2)
ztemp(i%) = pprime(3)
NEXT
END SUB
'------------------------------------------------------------------------------
' perform 3D projection to projection plane, then 2D view transformation to viewport
'------------------------------------------------------------------------------
SUB draw.temp.world STATIC
'for compiler only:
' dim i%
FOR i% = 1 TO num.points%
xp(i%) = xtemp(i%)*d/(ztemp(i%)+cube.dist)
yp(i%) = ytemp(i%)*d/(ztemp(i%)+cube.dist)
NEXT
pic2$ = pic1$
PICTURE ON
PENMODE 10 'pen mode XOR so it is erased when drawn again
MOVETO FNxv%(xp(1)),FNyv%(yp(1)) 'must use Toolbox routines for XOR to work
LINETO FNxv%(xp(2)),FNyv%(yp(2))
LINETO FNxv%(xp(3)),FNyv%(yp(3))
LINETO FNxv%(xp(4)),FNyv%(yp(4))
LINETO FNxv%(xp(5)),FNyv%(yp(5))
LINETO FNxv%(xp(6)),FNyv%(yp(6))
LINETO FNxv%(xp(1)),FNyv%(yp(1))
LINETO FNxv%(xp(7)),FNyv%(yp(7))
LINETO FNxv%(xp(5)),FNyv%(yp(5))
MOVETO FNxv%(xp(3)),FNyv%(yp(3))
LINETO FNxv%(xp(7)),FNyv%(yp(7))
MOVETO FNxv%(xp(2)),FNyv%(yp(2))
LINETO FNxv%(xp(8)),FNyv%(yp(8))
LINETO FNxv%(xp(6)),FNyv%(yp(6))
MOVETO FNxv%(xp(4)),FNyv%(yp(4))
LINETO FNxv%(xp(8)),FNyv%(yp(8))
PICTURE OFF
pic1$ = PICTURE$
'erase previous cube:
PICTURE ,pic2$
'draw cube object:
PICTURE ,pic1$
END SUB
'------------------------------------------------------------------------------
' set parameters for 3D view transformation
'------------------------------------------------------------------------------
SUB set.view STATIC
'distance from origin to projection plane:
d = 2
'wwindow coordinates (on projection plane):
xw1 = -1
xw2 = 1
yw1 = 1
yw2 = -1
'viewport coordinates:
xv1% = 30
yv1% = 30
xv2% = 330
yv2% = 330
WINDOW 1,,(xv1%,yv1%)-(xv2%,yv2%),3
END SUB
'------------------------------------------------------------------------------
' initialize global objects
'------------------------------------------------------------------------------
SUB initialize.world STATIC
'for compiler only:
' dim i%
num.objects% = 1
num.points% = 8
x(1) = 1
y(1) = 1
z(1) = 1
x(2) = 1
y(2) = 1
z(2) = -1
x(3) = 1
y(3) = -1
z(3) = -1
x(4) = -1
y(4) = -1
z(4) = -1
x(5) = -1
y(5) = -1
z(5) = 1
x(6) = -1
y(6) = 1
z(6) = 1
x(7) = 1
y(7) = -1
z(7) = 1
x(8) = -1
y(8) = 1
z(8) = -1
'FOR i% = 1 TO num.points%
' z(i%) = z(i%) + cube.dist 'move object away from origin/eye location
'NEXT
END SUB
'------------------------------------------------------------------------------
' multiply two 4x4 matrices - produces a 4x4 matrix
'------------------------------------------------------------------------------
SUB mat.mat (a(),b(),mresult()) STATIC
'for compiler only:
' dim r%,c%
FOR r% = 1 TO 4
FOR c% = 1 TO 4
mresult(r%,c%) = a(r%,1)*b(1,c%)+a(r%,2)*b(2,c%)+a(r%,3)*b(3,c%)+a(r%,4)*b(4,c%)
NEXT
NEXT
END SUB
'------------------------------------------------------------------------------
' copy a 4x4 matrix
'------------------------------------------------------------------------------
SUB mat.copy (a(),b()) STATIC
'for compiler only:
' dim r%,c%
FOR r% = 1 TO 4
FOR c% = 1 TO 4
a(r%,c%) = b(r%,c%)
NEXT
NEXT
END SUB
'------------------------------------------------------------------------------
' multiply 4-vector by 4x4 matrix - produces a 4-vector
'------------------------------------------------------------------------------
SUB vect.mat (v(),m(),vresult()) STATIC
'for compiler only:
' dim c%
FOR c% = 1 TO 4
vresult(c%) = v(1)*m(1,c%)+v(2)*m(2,c%)+v(3)*m(3,c%)+v(4)*m(4,c%)
NEXT
END SUB
'------------------------------------------------------------------------------
' create 4x4 identity matrix
'------------------------------------------------------------------------------
SUB identity (m()) STATIC
'for compiler only:
' dim r%,c%
FOR r% = 1 TO 4
FOR c% = 1 TO 4
IF r% = c% THEN
m(r%,c%) = 1
ELSE
m(r%,c%) = 0
END IF
NEXT
NEXT
END SUB
'------------------------------------------------------------------------------
' create 4x4 transformation matrix for rotation about x axis
' (assumes m is initially the identity matrix or a former rotate.x matrix)
'------------------------------------------------------------------------------
SUB rotate.x (theta,m()) STATIC
'for compiler only:
' dim ct,st
'calculate these only once for efficiency:
ct = COS(theta)
st = SIN(theta)
m(2,2) = ct
m(2,3) = st
m(3,2) = -st
m(3,3) = ct
END SUB
'------------------------------------------------------------------------------
' create 4x4 transformation matrix for rotation about y axis
' (assumes m is initially the identity matrix or a former rotate.y matrix)
'------------------------------------------------------------------------------
SUB rotate.y (theta,m()) STATIC
'for compiler only:
' dim ct,st
'calculate these only once for efficiency:
ct = COS(theta)
st = SIN(theta)
m(1,1) = ct
m(1,3) = -st
m(3,1) = st
m(3,3) = ct
END SUB
'------------------------------------------------------------------------------
' create 4x4 transformation matrix for rotation about z axis
' (assumes m is initially the identity matrix or a former rotate.z matrix)
'------------------------------------------------------------------------------
SUB rotate.z (theta,m()) STATIC
'for compiler only:
' dim ct,st
'calculate these only once for efficiency:
ct = COS(theta)
st = SIN(theta)
m(1,1) = ct
m(1,2) = st
m(2,1) = -st
m(2,2) = ct
END SUB
'------------------------------------------------------------------------------
' create 4x4 transformation matrix for translation
' (assumes m is initially the identity matrix or a former translation matrix)
'------------------------------------------------------------------------------
SUB translate (tx,ty,tz,m()) STATIC
m(4,1) = tx
m(4,2) = ty
m(4,3) = tz
END SUB
'------------------------------------------------------------------------------
' create 4x4 transformation matrix for scaling
' (assumes m is initially the identity matrix or a former scaling matrix)
'------------------------------------------------------------------------------
SUB scale (sx,sy,sz,m()) STATIC
m(1,1) = sx
m(2,2) = sy
m(3,3) = sz
END SUB